from common import wx
from tuntun.settings import WX
from .error_code import ErrCode
from apps.message.models import *
from django.db import transaction
from apps.message.views import *

from tuntun.settings import PAY_EXPIRE_TIME, ORDER_MOBILE_STR, RANDOM_LEN, PRE_SALE_BLOCK_LOCK_TIME
import datetime
import time
from random import choice
from common.exceptions import JsonAPIException
import json
from decimal import *
from django.db.models import Q
from django.db.models import Avg, Count, Sum
from tuntun.settings import ALIPAY, LOGISTICS_AMOUNT
from sdks.alipay import AliPay
from .flows import OrderFlow
import copy
from rest_framework.parsers import FormParser
from common.restframework_parsers import XmlParser
from django.http import HttpResponse
from apps.system.models import SystemSetting
from tuntun.settings import NORMAL_USER_PRE_SALE_ORDER_LIMIT
from apps.mix import tasks
from tuntun.settings import APP_DOWNLOAD_LINK
from apps.mix.models import TaskProcess
from apps.repo.models import Repo, StoreUnitThree
from django.core.paginator import Paginator
from tuntun.settings import ExpressInfo
from django.contrib.auth.hashers import check_password


# Create your views here.


order_no = Order.make_order_no


class CreateOrderPreView(BaseAPIView):
    """
    1.创建预售订单

    {"fae648e746344c08a729b3952cc6d5ea":{"price": "679.00", "goods_blocks": [{"id": "8471c22f9e7f4bc394a7dc0d96b5a868", "repo_id": "55b78c67028648e689dc273e928de72c"}]}}
    """

    def post(self, request, *args, **kwargs):
        user = request.user
        data = request.data
        print(data)
        amount = 0
        order_count = 0
        if user.certificate_state == User.CertificateState.UNVERIFIED.name:
            raise JsonAPIException(ErrCode.CERTIFICATE_UNVERIFIED.name, ErrCode.CERTIFICATE_UNVERIFIED.value)

        with transaction.atomic():
            # 创建订单
            order_obj = Order()
            order_obj.Status = "CREATED"
            order_obj.no = order_no(user.mobile)
            order_obj.amount = Decimal('0.00')
            order_obj.buyer_user_id = user.id
            order_obj.create_type = Order.CreateType.PRE_SALE_BUY_IN.name
            order_obj.expire_at = time.time() + PAY_EXPIRE_TIME
            order_obj.save()
            unsaved_sos = []
            for key in data:  # 循环产品
                product_id = key
                items = data[key]
                repo_id = items.get('repo_id', '')

                try:
                    count = int(items.get('count', 0))
                except:
                    count = 0

                if count == 0:
                    raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='购买数量为0，无法下单')

                products = Product.objects.filter(id=product_id, status="PRE_SALE_ING")
                if products.count() == 0:
                    raise JsonAPIException(ErrCode.PRODUCT_ERROR.name, ErrCode.PRODUCT_ERROR.value, errors=[])
                product = products[0]
                if product.stock == 0:
                    raise JsonAPIException(ErrCode.STOCK_NONE.name, ErrCode.STOCK_NONE.value, errors=[])

                gbs = GoodsBlock.objects.filter(product_id=product_id, sold=False, locked_by_user_id=user.id)

                if gbs.count() != count:
                    raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='区块已超时释放，请重新返回下单')

                gbs.update(locked_expire_at=time.time()+PAY_EXPIRE_TIME)

                new_repo = Repo.objects.get(id=repo_id)
                new_repo_id = new_repo.id
                new_repo_name = new_repo.name
                old_repo = Repo.objects.get(id=gbs[0].repo_id)
                old_repo_id = old_repo.id
                old_repo_name = old_repo.name
                old_repo_cost_price_per_100g_1d = old_repo.price_per_100g_1d

                for good in gbs:  # 循环区块
                    g_id = good.id

                    old_repo_id = good.repo_id

                    # 创建子订单
                    suborder = SubOrder(order_id=order_obj.id,
                                        goods_block_id=g_id,
                                        product_id=product_id,
                                        product_name=product.name,
                                        goods_block_repo_id=old_repo_id,
                                        goods_block_repo_name=old_repo_name,
                                        store_unit_id=good.store_unit_id,
                                        price_per_100g_1d=good.repo_cost_price_per_100g_1d,
                                        amount=product.pre_sale_price,
                                        create_type="PRE_SALE_BUY_IN",
                                        repo_cost_start_datetime=datetime.datetime.now(),
                                        repo_cost_end_datetime=datetime.datetime.now(),
                                        goods_block_to_repo_id=new_repo_id,
                                        goods_block_to_repo_name=new_repo_name,
                                        )
                    unsaved_sos.append(suborder)

                order_count += count

                # 更改总价
                order_obj.amount += Decimal(str(count))*product.pre_sale_price

            SubOrder.objects.bulk_create(unsaved_sos)

            ex_time = time.time() + PAY_EXPIRE_TIME
            order_obj.expire_at = ex_time
            order_obj.save()

        return Response({
            "id": order_obj.id,
            "no": order_obj.no,
            "amount": order_obj.amount,
            "count": order_count,
            "expire_at": order_obj.expire_at,
            "grow_coins": order_obj.grow_coins
        })


class CreateOrderBuyView(BaseAPIView):
    """
    买入下单
    """

    def post(self, request, *args, **kwargs):
        import time
        import datetime
        user = request.user
        data = copy.copy(request.data)
        resp = {}
        # 实名认证判断
        if user.certificate_state == User.CertificateState.UNVERIFIED.name:
            raise JsonAPIException(ErrCode.CERTIFICATE_UNVERIFIED.name, ErrCode.CERTIFICATE_UNVERIFIED.value)

        with transaction.atomic():
            # 创建订单
            order_amount = Decimal('0.00')
            order = Order()
            order.create_type = Order.CreateType.MARKET_BUY_IN.name
            order.Status = Order.Status.CREATED.name
            order.no = order_no(user.mobile)
            order.amount = Decimal('0.00')
            order.buyer_user_id = user.id
            order.expire_at = time.time() + PAY_EXPIRE_TIME

            all_repo_amount = 0
            gbs_count = 0

            for key in data:
                seller_user_id = key
                seller_data = data[seller_user_id]
                goods_blocks = seller_data["goods_blocks"]
                market_order_id = seller_data['market_order_id']

                market_order = MarketOrder.objects.filter(pk=market_order_id).first()
                if not market_order:
                    raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='挂单不存在', status=400)
                gbs = GoodsBlock.objects.filter(
                    id__in=[e['id'] for e in goods_blocks],
                    market_order=market_order,
                    product_id=market_order.product.id)
                if gbs.count() < len(goods_blocks):
                    raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='所选产品数量错误', status=400)
                if market_order.buy_in_market_order:  # 满足TA或自动匹配, 所选区块数必须和挂单区块数一样
                    if gbs.count() != GoodsBlock.objects.filter(market_order=market_order).count():
                        raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='所选产品数量和挂单数量不匹配')

                gb_repo_map = {e['id']: e['repo_id'] for e in goods_blocks}
                for gb in gbs:  # 循环区块
                    to_repo = Repo.objects.filter(pk=gb_repo_map[gb.id]).first()
                    if not to_repo:
                        raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='换仓参数错误', status=400)
                    # 仓储天数
                    # 仓储费（天 * 仓储费 * 重量）
                    all_repo_amount += gb.repo_amount

                    # 子订单
                    suborder = SubOrder()
                    suborder.order_id = order.id
                    suborder.goods_block_id = gb.id
                    suborder.product_id = gb.product_id
                    suborder.product_name = gb.product.name
                    suborder.goods_block_repo_id = gb.repo.id
                    suborder.goods_block_repo_name = gb.repo.name
                    suborder.store_unit_id = gb.store_unit_id
                    suborder.price_per_100g_1d = gb.repo_cost_price_per_100g_1d
                    suborder.amount = gb.market_order.offered_price
                    suborder.create_type = SubOrder.CreateType.MARKET_BUY_IN.name
                    suborder.seller_user_id = seller_user_id
                    suborder.repo_cost_start_datetime = gb.trade_datetime
                    suborder.repo_cost_end_datetime = datetime.datetime.now()
                    suborder.market_order_id = market_order.id
                    suborder.repo_amount = gb.repo_amount
                    suborder.goods_block_to_repo_id = to_repo.id
                    suborder.goods_block_to_repo_name = to_repo.name
                    suborder.save()

                    # 计算总价值
                    order_amount = order_amount + market_order.offered_price

                # 挂单状态
                market_order.status = MarketOrder.Status.TRADE.name
                market_order.save()

                gbs_count += len(gbs)

            # 计算优惠价格
            all_repo_preferential_amount = SystemSetting.get_repo_cost_preferential_amount(user, all_repo_amount)
            all_repo_real_pay_amount = all_repo_amount - all_repo_preferential_amount  # 实际支付仓储费

            order.amount = order_amount

            # 计算手续费
            seller_user = User.objects.get(pk=SubOrder.objects.filter(order=order).first().seller_user_id)
            procedure = SystemSetting.get_procedure_preferential_amount(seller_user, order.amount)
            procedure_amount = procedure['procedure_amount']
            procedure_preferential_amount = procedure['procedure_preferential_amount']
            procedure_real_pay_amount = procedure['procedure_real_pay_amount']

            # 存仓费+手续费 < 支付金额
            if Decimal(all_repo_real_pay_amount) + Decimal(procedure_real_pay_amount) > Decimal(order_amount):
                raise JsonAPIException(ErrCode.MARKET_AMOUNT_EXCEPT.name, ErrCode.MARKET_AMOUNT_EXCEPT.value)

            # 更改主订单总价和支付超时时间
            ex_time = time.time() + PAY_EXPIRE_TIME
            order.expire_at = ex_time

            order.repo_amount = all_repo_amount
            order.repo_preferential_amount = all_repo_preferential_amount
            order.repo_real_pay_amount = all_repo_real_pay_amount

            order.procedure_amount = procedure_amount
            order.procedure_preferential_amount = procedure_preferential_amount
            order.procedure_real_pay_amount = procedure_real_pay_amount

            order.save()

            resp.update({
                'id': order.id,
                "no": order.no,
                "amount": order.amount,
                "count": gbs_count,
                "expire_at": ex_time,
                "grow_coins": order.grow_coins
            })

        return Response(resp)


class CreateOrderTakeView(BaseAPIView):
    """
    4.创建提仓订单
    """

    def post(self, request, *args, **kwargs):
        import time
        import datetime
        user = request.user
        data = copy.copy(request.data)
        resp = {}

        product_ids = data.keys()
        # if Product.objects.filter(id__in=product_ids).filter(id='3c0bca5876ae4cfd9a7566fb2be3e5c6'):
        #     raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='小黄盒6月1日之后开放提仓功能')

        with transaction.atomic():
            # 新建提仓主订单
            order = Order()
            order.Status = Order.Status.CREATED.name
            order.create_type = Order.CreateType.TAKE_OUT.name
            order.no = order_no(user.mobile)
            order.amount = Decimal('0.00')
            order.repo_amount = Decimal('0.00')
            order.buyer_user_id = user.id
            order.expire_at = time.time() + PAY_EXPIRE_TIME
            # 计算手续费
            # procedure = SystemSetting.get_procedure_preferential_amount(user)
            procedure_amount = Decimal('0.00')
            procedure_preferential_amount = Decimal('0.00')
            procedure_real_pay_amount = Decimal('0.00')
            order.procedure_amount = procedure_amount
            order.procedure_preferential_amount = procedure_preferential_amount
            order.procedure_real_pay_amount = procedure_real_pay_amount
            order.save()

            product_id = ""
            gbs_count = 0
            for key in data:
                product_id = key
                items = data[product_id]
                goods_blocks = items["goods_blocks"]

                gbs = GoodsBlock.objects.filter(
                    id__in=[e['id'] for e in goods_blocks],
                    product_id=product_id, owner_user_id=user.id)
                if gbs.count() < len(goods_blocks):
                    raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='所选产品数量错误', status=400)

                # 新建提仓挂单
                m_order = MarketOrder()
                m_order.user_id = user.id
                m_order.product_id = product_id
                m_order.intention_type = MarketOrder.IntentionType.TAKE_OUT.name
                m_order.offered_price = 0
                m_order.publish_type = MarketOrder.PublishType.TAKE_OUT.name
                m_order.status = MarketOrder.Status.TRADE.name
                m_order.as_gift = False
                m_order.count = gbs.count()
                m_order.save()

                for good_block in gbs:
                    # 修改区块
                    good_block.trade_type = GoodsBlock.TradeType.TAKE_OUT.name
                    good_block.market_order = m_order
                    good_block.save()

                    # 添加提仓子订单
                    new_suborder = SubOrder()
                    new_suborder.order = order
                    new_suborder.goods_block_id = good_block.id
                    new_suborder.product_id = product_id
                    new_suborder.product_name = good_block.product.name
                    new_suborder.goods_block_repo_id = good_block.repo_id
                    new_suborder.goods_block_repo_name = good_block.repo.name
                    new_suborder.store_unit_id = good_block.store_unit_id
                    new_suborder.price_per_100g_1d = good_block.repo_cost_price_per_100g_1d
                    new_suborder.amount = Decimal('0.00')
                    new_suborder.seller_user_id = user.id
                    new_suborder.market_order_id = m_order.id
                    new_suborder.create_type = SubOrder.CreateType.TAKE_OUT.name
                    new_suborder.repo_cost_start_datetime = good_block.trade_datetime
                    new_suborder.repo_cost_end_datetime = datetime.datetime.now()

                    sub_repo_amount = good_block.repo_amount

                    new_suborder.repo_amount = sub_repo_amount
                    new_suborder.save()

                    order.repo_amount += new_suborder.repo_amount

                gbs_count += gbs.count()
            order.repo_preferential_amount = SystemSetting.get_repo_cost_preferential_amount(user, order.repo_amount)
            order.repo_real_pay_amount = Decimal(order.repo_amount) - Decimal(order.repo_preferential_amount)

            order.logistics_amount = Decimal('0.00')
            order.logistics_preferential_amount = Decimal('0.00')
            order.logistics_real_pay_amount = Decimal('0.00')

            order.amount = order.repo_real_pay_amount + order.logistics_real_pay_amount  # 总支付金额 = 实付仓储费 + 实付物流费
            order.expire_at = time.time() + PAY_EXPIRE_TIME
            order.use_take_out_free_postage_right_id = None
            order.save()

            product = Product.objects.filter(id=product_id).first()
            packages = Package.objects.filter(id__in=product.package_ids)
            packs = []
            for package in packages:
                packs.append({
                    "id": package.id,
                    "name": package.name,
                    "price": package.price,
                    "avatar": package.avatar,
                    "brand": product.brand.name,
                    "count": 0
                })
            resp.update({
                'id': order.id,
                "no": order.no,
                "amount": order.amount,
                "count": gbs_count,
                "repo_amount": order.repo_amount,
                "repo_preferential_amount": order.repo_preferential_amount,
                "repo_real_pay_amount": order.repo_real_pay_amount,
                "logistics_amount": order.logistics_amount,
                "logistics_preferential_amount": order.logistics_preferential_amount,
                "logistics_real_pay_amount": order.logistics_real_pay_amount,
                "expire_at": order.expire_at,
                "package": packs
            })
        return Response(resp)


class CreateOrderTakeUpdateView(BaseAPIView):
    """
    4-1.提仓信息修改
    ================
    """

    def post(self, request, *args, **kwargs):
        user = request.user
        data = copy.copy(request.data)
        order_id = kwargs["id"]
        address_id = data.get("address_id", '')
        package_ids = data.get("package_ids", [])

        if not address_id:
            raise JsonAPIException(ErrCode.ORDER_ADDRESS.name, ErrCode.ORDER_ADDRESS.value)

        order = Order.objects.filter(id=order_id).first()

        if order.status != Order.Status.CREATED.name:
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='订单当前状态不能修改提仓信息')

        if order == None:
            raise JsonAPIException(ErrCode.ORDER_NULL.name, ErrCode.ORDER_NULL.value)

        address = Address.objects.filter(id=address_id).first()
        if not address:
            raise JsonAPIException(ErrCode.ORDER_ADDRESS.name, ErrCode.ORDER_ADDRESS.value)

        administrative_area_info = address.administrative_area_info
        if len(administrative_area_info) == 0 or administrative_area_info[-1][0] not in ['A', 'B', 'C', 'D', 'E']:
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='地址不可用，请返回重新编辑地址')

        # 计算快递费
        first_kg_price = 26
        rest_kg_price = 21
        first_sub_order = SubOrder.objects.filter(order=order).first()
        product = Product.objects.get(pk=first_sub_order.product_id)
        src_code = ExpressInfo.src_code
        dest_code = administrative_area_info[-1]
        # 计算重量
        tct = product.tea_cake_type
        if tct in [Product.TeaCakeType.SMALL.name, Product.TeaCakeType.G50.name]:
            weight = 1000
        elif tct in [Product.TeaCakeType.G200.name, Product.TeaCakeType.G375.name, Product.TeaCakeType.G250.name]:
            weight = SubOrder.objects.filter(order=order).count() * 500
        elif tct in [Product.TeaCakeType.G500.name,]:
            weight = SubOrder.objects.filter(order=order).count() * 1000
        else:
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='不支持的茶饼类型')

        infos = []
        weight_kg_amount = round(weight / 1000, 3)
        if weight_kg_amount == 0.0:
            weight_kg_amount = 0.001
        status, express_cost = SystemSetting.get_postage(src_code, dest_code, weight_kg_amount)
        if not status:
            infos.append(express_cost)
            dest_code = administrative_area_info[-2]
            status, express_cost = SystemSetting.get_postage(src_code, dest_code, weight_kg_amount)
            if not status:
                infos.append(express_cost)
                # 无法在线计算运费的时候，按首重26，每增加1kG加21元
                if int(weight_kg_amount) == weight_kg_amount:  # 整数kG
                    express_cost = 26 + (int(weight_kg_amount)-1)*21
                else:
                    weight_kg_amount = int(weight_kg_amount) + 1
                    express_cost = 26 + (weight_kg_amount-1)*21


        logistics_amount = Decimal(str(express_cost))
        postage_preferential, use_take_out_free_postage_right_id = SystemSetting.get_postage_preferential(user, logistics_amount)
        logistics_preferential_amount = postage_preferential
        logistics_real_pay_amount = Decimal(logistics_amount) - Decimal(logistics_preferential_amount)

        with transaction.atomic():

            order.address_id = address_id
            order.address_mobile = address.mobile
            order.address_name = address.name
            order.address_full_address = address.full_address
            order.logistics_amount = logistics_amount
            order.logistics_preferential_amount = logistics_preferential_amount
            order.logistics_real_pay_amount = logistics_real_pay_amount
            order.use_take_out_free_postage_right_id = use_take_out_free_postage_right_id
            # 批量删除已添加包装
            OrderPackage.objects.filter(order_id=order.id).delete()
            order.packages_amount = Decimal('0.00')

            for pack in package_ids:
                pack_id = pack.get("id", '')
                package = Package.objects.filter(id=pack_id).first()
                if not package:
                    raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='所选包装不存在或不可用')
                pack_count = pack["count"]
                order_package = OrderPackage(order=order, package_id=pack_id, name=package.name,
                                             price=package.price,
                                             count=pack_count, avatar_public_file_id=package.avatar_public_file_id)
                order_package.save()

                order.packages_amount += Decimal(package.price * pack_count)

            order.amount = order.repo_real_pay_amount + order.procedure_real_pay_amount + order.logistics_real_pay_amount + order.packages_amount
            order.save()

        resp = {
            'id': order.id,
            "no": order.no,
            "amount": order.amount.__str__(),
            "repo_amount": order.repo_amount.__str__(),
            "repo_preferential_amount": order.repo_preferential_amount.__str__(),
            "repo_real_pay_amount": order.repo_real_pay_amount.__str__(),
            "logistics_amount": order.logistics_amount.__str__(),
            "logistics_preferential_amount": order.logistics_preferential_amount.__str__(),
            "logistics_real_pay_amount": order.logistics_real_pay_amount.__str__(),
            "expire_at": order.expire_at,
            "package_amount": order.packages_amount.__str__(),
            "package_count": OrderPackage.objects.filter(order=order).count(),
            "infos": infos,
        }

        return Response(resp)


class GiftOrderView(BaseAPIView):
    """
    我的/消息通知/赠送/接受
    POST    /order/gift/orders
    """

    def post(self, request, *args, **kwargs):
        user = request.user
        order = request.data
        if user.certificate_state == User.CertificateState.UNVERIFIED.name:
            raise JsonAPIException(ErrCode.CERTIFICATE_UNVERIFIED.name, ErrCode.CERTIFICATE_UNVERIFIED.value)

        with transaction.atomic():
            market_id = order["market_id"]
            market_order = MarketOrder.objects.get(pk=market_id)
            goods = GoodsBlock.objects.filter(market_order_id=market_id)

            if market_order == None or market_order.status == MarketOrder.Status.CANCELED.name or goods.count() == 0:
                raise JsonAPIException(ErrCode.MARKET_NULL.name, ErrCode.MARKET_NULL.value)

            for good_block in goods:
                if good_block:
                    seller = good_block.owner_user_id
                    good_block.owner_user_id = user.id
                    good_block.trade_type = GoodsBlock.TradeType.MARKET.name
                    good_block.trade_price = good_block.product.last_trade_price
                    good_block.market_order = None
                    good_block.locked_by_user_id = None
                    good_block.locked_expire_at = 0
                    good_block.save()

                    # 仓储天数
                    now = datetime.datetime.now()
                    start = good_block.trade_datetime
                    cha_time = now - start
                    days = cha_time.days + 1

                    seller_block = GoodsBlockChain.objects.create(goods_block_id=good_block.id,
                                                                  operator_user_id=seller,
                                                                  chain_type=GoodsBlockChain.ChainType.DIRECT_GIVE.name,
                                                                  node_datetime=datetime.datetime.now(),
                                                                  storage_repo_id=good_block.repo_id,
                                                                  storage_repo_days=days
                                                                  )
                    buyer_block = GoodsBlockChain.objects.create(goods_block_id=good_block.id,
                                                                 operator_user_id=user.id,
                                                                 chain_type=GoodsBlockChain.ChainType.ACCEPT.name,
                                                                 node_datetime=datetime.datetime.now(),
                                                                 storage_repo_id=good_block.repo_id,
                                                                 storage_repo_days=days
                                                                 )
            # 处理订单和挂单
            market_order.related_order.status = Order.Status.FINISHED.name
            market_order.related_order.update_timestamp = time.time()
            market_order.related_order.save()
            market_order.status = MarketOrder.Status.END.name
            market_order.update_timestamp = time.time()
            market_order.save()
        return Response({})


class GiftRefuseView(BaseAPIView):
    """
    我的/消息通知/赠送/拒绝(不送了)
    POST    /order/gift/refuse/
    type :
        refuse   拒绝
        cancel   取消

    """

    def post(self, request, *args, **kwargs):
        user = request.user
        order = request.data
        type = kwargs['type']
        market_id = order["market_id"]
        order_id = order["order_id"]

        # 挂单结束
        market = MarketOrder.objects.filter(id=market_id, as_gift=True).first()
        # 订单结束
        order = market.related_order

        if not market:
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='挂单不存在或已失效')

        if type == "refuse":  # 拒絕
            if market.as_gift_multiple:
                raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='多人赠送无需操作')

            # 余额回退
            re_amount = Decimal(order.amount)
            if order.status == Order.Status.PAYED.name and order.buyer_user_id == user.id:
                order.status = Order.Status.GIFT_BE_REJECTED.name
                order.save()

                market.status = MarketOrder.Status.END.name
                market.save()

                if order.buyer_user_id == user.id:
                    sell_user = User.objects.filter(id=market.user_id).first()
                    sell_user.balance += Decimal(re_amount)
                    sell_user.save()
                    # 记录退款流向
                    UserBalanceRecord.objects.create(user=sell_user,
                                                     create_type=UserBalanceRecord.CreateType.GIFT_REPO_COST_REFUND.name,
                                                     amount=re_amount,
                                                     order_id=order.id)
                # 区块释放
                goods = GoodsBlock.objects.filter(market_order_id=market_id)
                for good_block in goods:
                    if good_block:
                        good_block.market_order = None
                        good_block.locked_by_user_id = None
                        good_block.locked_expire_at = 0
                        good_block.save()

        elif type == "cancel":  # 取消
            if market.user_id == user.id:
                if market.as_gift_multiple:
                    if SubOrder.objects.filter(market_order_id=market.id):
                        raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='多人赠送已有人领取，无法取消')
                if not market.as_gift_multiple:
                    # 余额回退
                    re_amount = Decimal(order.amount)
                    order.status = Order.Status.CANCELED.name
                    order.save()

                    sell_user = User.objects.filter(id=user.id).first()
                    sell_user.balance += Decimal(re_amount)
                    sell_user.save()
                    # 记录退款流向
                    UserBalanceRecord.objects.create(user=sell_user,
                                                     create_type=UserBalanceRecord.CreateType.GIFT_REPO_COST_REFUND.name,
                                                     amount=re_amount,
                                                     order_id=order.id)
                # 区块释放
                goods = GoodsBlock.objects.filter(market_order_id=market_id)
                for good_block in goods:
                    if good_block:
                        good_block.market_order = None
                        good_block.locked_by_user_id = None
                        good_block.locked_expire_at = 0
                        good_block.save()

                market.status = MarketOrder.Status.CANCELED.name
                market.save()

        return Response({})


class GiftEditView(BaseAPIView):
    """
    编辑
    POST    /order/gift/edit
    """

    def post(self, request, *args, **kwargs):
        order = request.data
        market_id = order["market_id"]
        as_gift_append_memo = order["as_gift_append_memo"]

        # 挂单结束
        market = MarketOrder.objects.filter(id=market_id, as_gift=True, status=MarketOrder.Status.ING.name).first()
        if market:
            market.as_gift_append_memo = as_gift_append_memo
            market.save()
        else:
            raise JsonAPIException(ErrCode.MARKET_NULL.name, ErrCode.MARKET_NULL.value, status=400)

        return Response({})


class OrderDetailView(BaseAPIView):
    """获取订单详情数据"""
    permission_classes = ()

    def get(self, request, *args, **kwargs):
        ret = {"app_download_link": APP_DOWNLOAD_LINK}
        id = kwargs.get('id', '')
        order = Order.objects.filter(pk=id).first()
        if not order:
            market_order = MarketOrder.objects.filter(pk=id).first()
            if not market_order:
                raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='信息不存在或已删除')
        else:
            if order.status not in [Order.Status.PAYED.name, Order.Status.FINISHED.name]:
                raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='当前信息状态不允许查看')
            market_order = order.market_order if order.market_order else None
            if not market_order:
                raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='信息不允许查看')

        product = market_order.product

        tpd = product.today_price_data
        wpd = product.week_price_data
        mpd = product.month_price_data

        ret['product_info'] = {
            "id": product.id,
            "logo": product.logo,
            "name": product.name,
            "brand": product.brand.name,
            "store_id": product.brand.store.id,
            "store": product.brand.store.name,
            "keeping_count": product.keeping_count,
            "status": product.status,
            "status_map": dict(Product.ProductStatus.get_choices()),
            "avg_price": product.avg_price_custom,
            "up_down_percent": '%.2f%%' % (product.up_down_percent * 100),
            "today_price_data": tpd,
            "week_price_data": wpd,
            "month_price_data": mpd,
        }

        seller_user = User.objects.filter(pk=market_order.user_id).first()
        if seller_user:
            ret['gift_info'] = {
                'seller_user_id': seller_user.id,
                'as_gift': market_order.as_gift,
                'as_gift_multiple': market_order.as_gift_multiple,
                'seller_user_nickname': seller_user.nickname,
                'as_gift_append_memo': market_order.as_gift_append_memo,
                'count': market_order.count,
            } if market_order.as_gift else {}
        else:
            ret['gift_info'] = {}
        return Response(ret)


class DeleteOrderView(BaseAPIView):
    """删除订单"""

    def post(self, request, *args, **kwargs):
        with transaction.atomic():
            marketorder = MarketOrder.objects.filter(id=request.data['market_id']).first()
            if marketorder:
                #
                msg = Message.objects.filter(market_order_id=marketorder.id).update(deleted_at=time.time())
                UserHistoryMessage.objects.filter(history_message_id=msg).update(deleted_at=time.time())
                marketorder.soft_delete()
                #

        return Response({})


class GetGoodBlockPre(BaseAPIView):
    """
    1.预售买入下单时请求商品区块
    ===============
    POST     /order/pre-sale/products/:product_id/blocks
    """

    def post(self, request, *args, **kwargs):
        user = request.user
        product_id = kwargs["product_id"]
        order = request.data
        count = int(order["count"])
        print(count, "count")

        resp = {'count': 0, 'items': []}

        try:
            offset = int(request.GET.get('offset', -1))
            limit = int(request.GET.get('limit', -1))
        except:
            offset = -1
            limit = -1

        if count > user.get_pre_sale_order_limit(product_id):
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='预售单次下单数量超限')

        with transaction.atomic():
            GoodsBlock.objects.filter(locked_by_user_id=user.id, product_id=product_id, sold=False).update(
                locked_by_user_id=None, locked_expire_at=0)

            gbs = GoodsBlock.objects.filter(sold=False, product_id=product_id, locked_by_user_id=None, locked_expire_at=0)
            if gbs.count() < count:
                raise JsonAPIException(code=ErrCode.STOCK_NONE.name, msg='库存不足或剩余区块已被其他用户锁定，请稍后重试')

            gbs = gbs[0:count]

            GoodsBlock.objects.filter(id__in=[e.id for e in gbs]).update(locked_by_user_id=user.id, locked_expire_at=time.time()+PRE_SALE_BLOCK_LOCK_TIME)

            if offset == -1 and limit == -1:
                objs = gbs
            else:
                try:
                    paginator = Paginator(gbs, limit)
                    req_page = offset // limit + 1
                    objs = paginator.page(req_page).object_list
                except:
                    count = 0
                    objs = []

            resp['count'] = count
            for gb in objs:
                resp['items'].append(gb.get_block_order())
        return Response(resp)


class GetGoodBlockTrade(BaseAPIView):
    """
    2.互易买入下单时请求商品区块（获取该挂单的所有区块）
    ===========================
        GET     /order/trade/market-orders/:id/blocks
    """

    def get(self, request, *args, **kwargs):
        resp = {'count': "0", 'items': [], "repo_items": []}
        m_orders = MarketOrder.objects.filter(id=kwargs["id"])
        if m_orders.count() > 0:
            m_order = m_orders[0]
            good_blocks = GoodsBlock.objects.filter(market_order_id=m_order)
            resp["count"] = good_blocks.count()
            for good_block in good_blocks:
                resp["items"].append(good_block.get_block_order())

        if good_blocks.count() > 0:
            resp['repo_items'].append(good_blocks.first().repo_list())
        return Response(resp)


class DetailOrderView(BaseAPIView):
    """
    订单详情(获取blocks列表)
    ================
    GET     /order/orders/:id/blocks
    """

    def get(self, request, *args, **kwargs):
        order_id = kwargs["id"]

        suborders = SubOrder.objects.filter(order_id=order_id)
        resp = {"count": suborders.count(), "items": []}
        for order in suborders:
            good = GoodsBlock.objects.filter(id=order.goods_block_id).first()
            if good:
                resp["items"].append(good.get_block_detail())
        return Response(resp)


class OrderPayView(BaseAPIView):
    """
    订单支付
    """

    def post(self, request, *args, **kwargs):
        id = kwargs.get('id', None)
        user = request.user
        payment_method = request.data.get('payment_method', None)
        pay_password = request.data.get('pay_password', None)
        resp = {}
        print(id, user,pay_password, payment_method)
        ret = check_password(pay_password, user.purse_password)
        if ret == False:
            raise JsonAPIException("PASSWORD_ERROR", "支付密码错误")

        order = Order.objects.get(pk=id)
        first_sub_order = SubOrder.objects.filter(order=order).first()
        if order.status not in [Order.Status.CREATED.name]:
            if order.status in [Order.Status.PAYED.name, Order.Status.FINISHED.name]:
                raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='订单已支付')
            if order.status in [Order.Status.CANCELED.name, Order.Status.EXPIRED.name]:
                raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='订单超时已取消')
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='订单已支付或已取消')
        if first_sub_order.create_type == SubOrder.CreateType.TAKE_OUT.name and not order.address_id:
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='收货地址未设置')

        order.payment_method = payment_method
        order.save()
        # 创建支付记录

        payment = Payment.objects.create(
            ptype=Payment.PType.TRADE.name,
            order=order,
            buyer_user_id=user.id,
            payment_method=payment_method,
            status=Payment.Status.WAITPAY.name,
        )
        resp['payment_id'] = payment.id
        if payment_method == Payment.PaymentMethod.ALI.name:
            alipay = AliPay(
                appid=ALIPAY['APPID'].strip(),
                app_notify_url=ALIPAY['NOTIFY_URL'],
                app_private_key_string=ALIPAY['APP_PRIVATE_KEY'].strip(),
                alipay_public_key_string=ALIPAY['ALIPAY_PUBLIC_KEY'].strip(),
                sign_type='RSA2',
                debug=False,
            )

            order_string = alipay.api_alipay_trade_app_pay(
                out_trade_no=order.no,
                total_amount=order.amount.__str__(),
                subject="囤囤订单支付",
                notify_url=ALIPAY['NOTIFY_URL'],
                payment_id=payment.id,
            )
            resp['alipay_order_string'] = order_string
        elif payment_method == Payment.PaymentMethod.WEIXIN.name:
            from common import wx
            now = datetime.datetime.now()
            expire = now + datetime.timedelta(seconds=600)
            order_pay_data = {}
            order_pay_data['body'] = str("囤囤茶交易支付订单")
            order_pay_data["out_trade_no"] = order.no
            order_pay_data["total_fee"] = int(float(order.amount.__str__()) * 100)
            order_pay_data['time_start'] = time.strftime('%Y%m%d%H%M%S')
            order_pay_data['time_expire'] = expire.strftime('%Y%m%d%H%M%S')
            order_pay_data['trade_type'] = wx.WxTradeType.APP.name
            order_pay_data['attach'] = payment.id

            status, code, data = wx.unified_order(WX, order_pay_data,
                                                  extra={'remote_addr': request.META['REMOTE_ADDR']})
            if not status:
                raise JsonAPIException(code=code, msg='微信支付统一下单失败', errors=[data], status=500)
            status, code, data = wx.get_apppay_parameters(WX, data)
            if not status:
                raise JsonAPIException(code=code, msg='获取APP客户端支付参数失败', errors=[data], status=500)
            resp['weixin_pay_params'] = data
        elif payment_method == Payment.PaymentMethod.BALANCE.name:
            with transaction.atomic():
                order.payment_method = Order.PaymentMethod.BALANCE.name
                user = User.objects.get(pk=request.user.id)
                if user.balance < order.amount:
                    raise JsonAPIException(code=ErrCode.BALANCE_NOT_SUFFICIENT.name, msg=ErrCode)

                # 处理主订单状态
                order.status = Order.Status.PAYED.name
                order.save()
                if order.as_gift:
                    # 余额变动
                    UserBalanceRecord.objects.create(user=user,
                                                     create_type=UserBalanceRecord.CreateType.GIFT_REPO_COST_PAY.name,
                                                     amount=Decimal('-' + order.amount.__str__()))
                    user.balance -= order.amount
                    user.save()

                    first_sub_order = SubOrder.objects.filter(order=order).first()

                    msg = CreateMessageView.message(msg_type=Message.MsgType.GIFT.name,
                                                    oper_user=User.objects.filter(
                                                        id=order.market_order.user_id).first(),
                                                    message_user_id=order.buyer_user_id,
                                                    product_name=first_sub_order.product_name,
                                                    order_id=order.id,
                                                    market_order_id=first_sub_order.market_order_id)

                    print('发送赠送消息： %s' % msg.id)
                    t = tasks.task_send_transmission_msg.delay(user_id=order.buyer_user_id, transmission_msg_data=msg.make_transmission_msg(), message_id=msg.id, with_push=True)


                else:
                    # 修改主订单状态 默认PAYED
                    if order.status == Order.Status.FINISHED.name:
                        raise JsonAPIException(ErrCode.ORDER_FINISH.name, ErrCode.ORDER_FINISH.value, [])

                    # 余额变动
                    first_sub_order = SubOrder.objects.filter(order=order).first()
                    if first_sub_order.create_type == SubOrder.CreateType.PRE_SALE_BUY_IN.name:
                        # 更新区块状态为已卖出
                        GoodsBlock.objects.filter(id__in=[so.goods_block_id for so in SubOrder.objects.filter(order=order)]).update(sold=True)
                        #
                        UserBalanceRecord.objects.create(user=user,
                                                         create_type=UserBalanceRecord.CreateType.BUY_PRE_SALE.name,
                                                         amount=Decimal('-' + order.amount.__str__()))
                        user.balance -= order.amount
                        user.save()
                        order.status = Order.Status.FINISHED.name
                        order.update_timestamp = time.time()
                        order.save()
                        # 预售购买成功消息
                        product_name=first_sub_order.product_name
                        count=SubOrder.objects.filter(order=order).count()
                        amount=order.amount
                        msg = CreateMessageView.message(msg_type=Message.MsgType.PRE_SALE.name,
                                                        oper_user=None,
                                                        message_user_id=order.buyer_user.id,
                                                        product_name=first_sub_order.product_name,
                                                        order_id=order.id,
                                                        market_order_id=None,
                                                        title="购买成功：亲爱的囤囤用户，您选择的「{product_name}」{count}饼购买成功，共支付{amount}元，预售结果我们将在「消息通知」内即使通知您，请注意查收。".format(product_name=product_name, count=count, amount=amount),
                                                        content='购买成功：亲爱的囤囤用户，您选择的「{product_name}」{count}饼购买成功，共支付{amount}元，预售结果我们将在「消息通知」内即使通知您，请注意查收。'.format(product_name=product_name, count=count, amount=amount))

                        t = tasks.task_send_transmission_msg.delay(user_id=order.buyer_user.id,
                                                                   transmission_msg_data=msg.make_transmission_msg(),
                                                                   message_id=msg.pk, with_push=True)
                        from apps.mix.models import TaskProcess
                        TaskProcess.objects.create(task_callable="task_send_transmission_msg",
                                                   task_name=tasks.task_send_transmission_msg.name, task_id=t.id)

                    elif first_sub_order.create_type == SubOrder.CreateType.MARKET_BUY_IN.name:
                        buyer = User.objects.get(pk=order.buyer_user_id)
                        buyer_ubr = UserBalanceRecord.objects.create(user=buyer,
                                                                     create_type=UserBalanceRecord.CreateType.MARKET_BUY_IN.name,
                                                                     amount=Decimal('-' + order.amount.__str__()))
                        buyer.balance -= order.amount
                        buyer.save()
                        seller = User.objects.get(pk=first_sub_order.seller_user_id)
                        seller_geted_amount = order.amount - order.repo_real_pay_amount
                        seller_ubr = UserBalanceRecord.objects.create(user=seller,
                                                                      create_type=UserBalanceRecord.CreateType.MARKET_SELL_OUT.name,
                                                                      amount=seller_geted_amount)
                        seller.balance += seller_geted_amount
                        seller.save()
                        order.status = Order.Status.FINISHED.name
                        order.update_timestamp = time.time()
                        order.save()
                    elif first_sub_order.create_type == SubOrder.CreateType.TAKE_OUT.name:
                        # 更新MarketOrder信息
                        market_order = MarketOrder.objects.get(pk=first_sub_order.market_order_id)
                        market_order.status = MarketOrder.Status.END.name
                        market_order.save()

                        GoodsBlock.objects.filter(market_order=market_order).update(taken_out=True)

                        UserBalanceRecord.objects.create(user=request.user,
                                                         create_type=UserBalanceRecord.CreateType.TAKE_OUT_REPO_COST_PAY.name,
                                                         amount=Decimal('-' + order.amount.__str__()))
                        user.balance -= order.amount
                        user.save()

                # 支付信息更新
                # payment = Payment.objects.get(order=order, status=Payment.Status.WAITPAY.name).order_by('-add_timestamp').first()
                payment.payment_method = Payment.PaymentMethod.BALANCE.name
                payment.status = Payment.Status.PAYED.name
                payment.water_no = order.no
                payment.settlement_total_fee = order.amount
                payment.provider_resp = ""
                payment.callbacked = False
                payment.save()

            # 对订单状态为FINISHED的订单后续处理
            first_sub_order = SubOrder.objects.filter(order=order).first()
            if order.status == Order.Status.FINISHED.name and first_sub_order.create_type != SubOrder.CreateType.PRE_SALE_BUY_IN.name:
                of = OrderFlow(order)
                of.post_trade_order_finished()
        elif payment_method == Payment.PaymentMethod.PURSEBALANCE.name:
            with transaction.atomic():
                order.payment_method = Order.PaymentMethod.PURSEBALANCE.name
                user = User.objects.get(pk=request.user.id)
                print(11111111111111)
                if user.purse_balance < order.amount:
                    raise JsonAPIException(code=ErrCode.BALANCE_NOT_SUFFICIENT.name, msg=ErrCode)

                # 处理主订单状态
                order.status = Order.Status.PAYED.name
                order.save()
                if order.as_gift:
                    # 余额变动
                    UserBalanceRecord.objects.create(user=user,
                                                     create_type=UserBalanceRecord.CreateType.GIFT_REPO_COST_PAY.name,
                                                     amount=Decimal('-' + order.amount.__str__()))
                    user.purse_balance -= order.amount
                    user.save()

                    first_sub_order = SubOrder.objects.filter(order=order).first()

                    msg = CreateMessageView.message(msg_type=Message.MsgType.GIFT.name,
                                                    oper_user=User.objects.filter(
                                                        id=order.market_order.user_id).first(),
                                                    message_user_id=order.buyer_user_id,
                                                    product_name=first_sub_order.product_name,
                                                    order_id=order.id,
                                                    market_order_id=first_sub_order.market_order_id)

                    print('发送赠送消息： %s' % msg.id)
                    t = tasks.task_send_transmission_msg.delay(user_id=order.buyer_user_id, transmission_msg_data=msg.make_transmission_msg(), message_id=msg.id, with_push=True)


                else:
                    # 修改主订单状态 默认PAYED
                    if order.status == Order.Status.FINISHED.name:
                        raise JsonAPIException(ErrCode.ORDER_FINISH.name, ErrCode.ORDER_FINISH.value, [])

                    # 余额变动
                    first_sub_order = SubOrder.objects.filter(order=order).first()
                    if first_sub_order.create_type == SubOrder.CreateType.PRE_SALE_BUY_IN.name:
                        # 更新区块状态为已卖出
                        GoodsBlock.objects.filter(id__in=[so.goods_block_id for so in SubOrder.objects.filter(order=order)]).update(sold=True)
                        #
                        UserBalanceRecord.objects.create(user=user,
                                                         create_type=UserBalanceRecord.CreateType.BUY_PRE_SALE.name,
                                                         amount=Decimal('-' + order.amount.__str__()))
                        user.purse_balance -= order.amount
                        user.save()
                        order.status = Order.Status.FINISHED.name
                        order.update_timestamp = time.time()
                        order.save()
                        # 预售购买成功消息
                        product_name=first_sub_order.product_name
                        count=SubOrder.objects.filter(order=order).count()
                        amount=order.amount
                        msg = CreateMessageView.message(msg_type=Message.MsgType.PRE_SALE.name,
                                                        oper_user=None,
                                                        message_user_id=order.buyer_user.id,
                                                        product_name=first_sub_order.product_name,
                                                        order_id=order.id,
                                                        market_order_id=None,
                                                        title="购买成功：亲爱的囤囤用户，您选择的「{product_name}」{count}饼购买成功，共支付{amount}元，预售结果我们将在「消息通知」内即使通知您，请注意查收。".format(product_name=product_name, count=count, amount=amount),
                                                        content='购买成功：亲爱的囤囤用户，您选择的「{product_name}」{count}饼购买成功，共支付{amount}元，预售结果我们将在「消息通知」内即使通知您，请注意查收。'.format(product_name=product_name, count=count, amount=amount))

                        t = tasks.task_send_transmission_msg.delay(user_id=order.buyer_user.id,
                                                                   transmission_msg_data=msg.make_transmission_msg(),
                                                                   message_id=msg.pk, with_push=True)
                        from apps.mix.models import TaskProcess
                        TaskProcess.objects.create(task_callable="task_send_transmission_msg",
                                                   task_name=tasks.task_send_transmission_msg.name, task_id=t.id)

                    elif first_sub_order.create_type == SubOrder.CreateType.MARKET_BUY_IN.name:
                        buyer = User.objects.get(pk=order.buyer_user_id)
                        buyer_ubr = UserBalanceRecord.objects.create(user=buyer,
                                                                     create_type=UserBalanceRecord.CreateType.MARKET_BUY_IN.name,
                                                                     amount=Decimal('-' + order.amount.__str__()))
                        buyer.purse_balance -= order.amount
                        buyer.save()
                        seller = User.objects.get(pk=first_sub_order.seller_user_id)
                        seller_geted_amount = order.amount - order.repo_real_pay_amount
                        seller_ubr = UserBalanceRecord.objects.create(user=seller,
                                                                      create_type=UserBalanceRecord.CreateType.MARKET_SELL_OUT.name,
                                                                      amount=seller_geted_amount)
                        seller.purse_balance += seller_geted_amount
                        seller.save()
                        order.status = Order.Status.FINISHED.name
                        order.update_timestamp = time.time()
                        order.save()
                    elif first_sub_order.create_type == SubOrder.CreateType.TAKE_OUT.name:
                        # 更新MarketOrder信息
                        market_order = MarketOrder.objects.get(pk=first_sub_order.market_order_id)
                        market_order.status = MarketOrder.Status.END.name
                        market_order.save()

                        GoodsBlock.objects.filter(market_order=market_order).update(taken_out=True)

                        UserBalanceRecord.objects.create(user=request.user,
                                                         create_type=UserBalanceRecord.CreateType.TAKE_OUT_REPO_COST_PAY.name,
                                                         amount=Decimal('-' + order.amount.__str__()))
                        user.balance -= order.amount
                        user.save()

                # 支付信息更新
                # payment = Payment.objects.get(order=order, status=Payment.Status.WAITPAY.name).order_by('-add_timestamp').first()
                payment.payment_method = Payment.PaymentMethod.PURSEBALANCE.name
                payment.status = Payment.Status.PAYED.name
                payment.water_no = order.no
                payment.settlement_total_fee = order.amount
                payment.provider_resp = ""
                payment.callbacked = False
                payment.save()

            # 对订单状态为FINISHED的订单后续处理
            first_sub_order = SubOrder.objects.filter(order=order).first()
            if order.status == Order.Status.FINISHED.name and first_sub_order.create_type != SubOrder.CreateType.PRE_SALE_BUY_IN.name:
                of = OrderFlow(order)
                of.post_trade_order_finished()
        else:
            raise JsonAPIException(ErrCode.PAYMENT_METHOD_UNSUPPORTED.name,
                                   ErrCode.PAYMENT_METHOD_UNSUPPORTED.value, status=400)

        if order.as_gift:
            buyer = User.objects.get(pk=order.buyer_user_id)
            resp['gift_info'] = {
                'to_user_nickname': buyer.nickname,
                'to_user_mobile': buyer.mobile,
                'to_memo': order.market_order.as_gift_append_memo,
                'product_logo': order.market_order.product.logo,
                'product_name': order.market_order.product.name,
                'brand_name': order.market_order.product.brand.name,
                "order_id": order.id,
            }

        return Response(resp)


class BaseOrderPayCallbackView(BaseAPIView):

    def pay_success(self, request, order, trade_no, total_amount, payment_id):
        with transaction.atomic():
            # 处理主订单状态
            first_sub_order = SubOrder.objects.filter(order=order).first()
            if order.as_gift:
                order.status = Order.Status.PAYED.name
                order.save()

                msg = CreateMessageView.message(msg_type=Message.MsgType.GIFT.name,
                                                oper_user=order.seller_user,
                                                message_user_id=order.buyer_user_id,
                                                product_name=first_sub_order.product_name,
                                                order_id=order.id,
                                                market_order_id=first_sub_order.market_order_id)

                t = tasks.task_send_transmission_msg.delay(user_id=order.buyer_user_id,
                                                           transmission_msg_data=msg.make_transmission_msg(),
                                                           message_id=msg.id, with_push=True)

                from apps.mix.models import TaskProcess
                TaskProcess.objects.create(task_callable='task_send_transmission_msg',
                                           task_name=tasks.task_send_transmission_msg.name, task_id=t.id)

            else:
                if first_sub_order.create_type in [SubOrder.CreateType.PRE_SALE_BUY_IN.name, ]:
                    # 修改主订单状态 默认PAYED
                    order.status = Order.Status.FINISHED.name
                    order.update_timestamp = time.time()
                    order.save()
                    # 更新区块状态为已卖出
                    GoodsBlock.objects.filter(
                        id__in=[so.goods_block_id for so in SubOrder.objects.filter(order=order)]).update(sold=True)
                    #
                    # 预售购买成功消息
                    product_name = first_sub_order.product_name
                    count = SubOrder.objects.filter(order=order).count()
                    amount = order.amount
                    msg = CreateMessageView.message(msg_type=Message.MsgType.PRE_SALE.name,
                                                    oper_user=None,
                                                    message_user_id=order.buyer_user.id,
                                                    product_name=first_sub_order.product_name,
                                                    order_id=order.id,
                                                    market_order_id=None,
                                                    title="购买成功：亲爱的囤囤用户，您选择的「{product_name}」{count}饼购买成功，共支付{amount}元，预售结果我们将在「消息通知」内即使通知您，请注意查收。".format(product_name=product_name, count=count, amount=amount),
                                                    content="购买成功：亲爱的囤囤用户，您选择的「{product_name}」{count}饼购买成功，共支付{amount}元，预售结果我们将在「消息通知」内即使通知您，请注意查收。".format(product_name=product_name, count=count, amount=amount))

                    t = tasks.task_send_transmission_msg.delay(user_id=order.buyer_user.id,
                                                           transmission_msg_data=msg.make_transmission_msg(),
                                                           message_id=msg.pk, with_push=True)
                    from apps.mix.models import TaskProcess
                    TaskProcess.objects.create(task_callable="task_send_transmission_msg",
                                               task_name=tasks.task_send_transmission_msg.name, task_id=t.id)

                elif first_sub_order.create_type in [SubOrder.CreateType.MARKET_BUY_IN.name, ]:
                    # 修改主订单状态 默认PAYED
                    order.status = Order.Status.FINISHED.name
                    order.update_timestamp = time.time()
                    order.save()

                    # 卖出消息
                    msg = CreateMessageView.message(msg_type=Message.MsgType.SOLD_OUT.name,
                                                    oper_user=User.objects.filter(
                                                        id=order.buyer_user_id).first(),
                                                    message_user_id=first_sub_order.seller_user_id,
                                                    product_name=first_sub_order.product_name,
                                                    order_id=order.id,
                                                    market_order_id=first_sub_order.market_order_id)

                    t = tasks.task_send_transmission_msg.delay(user_id=order.seller_user.id,
                                                           transmission_msg_data=msg.make_transmission_msg(),
                                                           message_id=msg.pk, with_push=True)
                    from apps.mix.models import TaskProcess
                    TaskProcess.objects.create(task_callable="task_send_transmission_msg",
                                               task_name=tasks.task_send_transmission_msg.name, task_id=t.id)

                    seller = User.objects.get(pk=first_sub_order.seller_user_id)
                    seller_geted_amount = order.amount - order.repo_real_pay_amount
                    seller_ubr = UserBalanceRecord.objects.create(user=seller,
                                                                  create_type=UserBalanceRecord.CreateType.MARKET_SELL_OUT.name,
                                                                  amount=seller_geted_amount)
                    seller.balance += seller_geted_amount
                    seller.save()
                    order.status = Order.Status.FINISHED.name
                    order.update_timestamp = time.time()
                    order.save()
                elif first_sub_order.create_type == SubOrder.CreateType.TAKE_OUT.name:
                    order.status = Order.Status.PAYED.name
                    order.save()
                    # 更新MarketOrder信息
                    seller_user = User.objects.get(pk=first_sub_order.seller_user_id)
                    market_order = MarketOrder.objects.get(pk=first_sub_order.market_order_id)
                    market_order.status = MarketOrder.Status.END.name
                    market_order.save()

                    GoodsBlock.objects.filter(market_order=market_order).update(taken_out=True)

                    UserBalanceRecord.objects.create(user=seller_user,
                                                     create_type=UserBalanceRecord.CreateType.TAKE_OUT_REPO_COST_PAY.name,
                                                     amount=Decimal('-' + order.amount.__str__()))

            # 对订单状态为FINISHED的订单后续处理
            first_sub_order = SubOrder.objects.filter(order=order).first()
            if order.status == Order.Status.FINISHED.name and first_sub_order.create_type != SubOrder.CreateType.PRE_SALE_BUY_IN.name:
                of = OrderFlow(order)
                of.post_trade_order_finished()
            print(order, order.pk)
        # 支付信息更新
        if payment_id:
            payment = Payment.objects.get(order=order, status=Payment.Status.WAITPAY.name, id=payment_id)
        else:
            payment = Payment.objects.filter(order=order, status=Payment.Status.WAITPAY.name).order_by('-add_timestamp').first()
        payment.status = Payment.Status.PAYED.name
        payment.water_no = trade_no
        payment.settlement_total_fee = total_amount
        payment.provider_resp = copy.copy(request.data)
        payment.callbacked = True
        payment.callback_type = Payment.CallbackType.APP.name
        payment.save()

    def pay_failed(self, request, order):
        payment = Payment.objects.get(order=order, status=Payment.Status.WAITPAY.name)
        payment.provider_resp = copy.copy(request.data)
        payment.callbacked = True
        payment.callback_type = Payment.CallbackType.APP.name
        payment.save()


class AlipayOrderPayProviderCallbackView(BaseOrderPayCallbackView):
    """支付宝订单支付-回调（Provider）"""
    permission_classes = ()
    parser_classes = (FormParser,)

    def post(self, request, *args, **kwargs):
        trade_status = request.data.get('trade_status')
        out_trade_no = request.data.get('out_trade_no')
        trade_no = request.data.get('trade_no')
        order = Order.objects.get(no=out_trade_no)
        print('-----', order.pk, '-------')
        if trade_status in 'TRADE_SUCCESS':
            total_amount = request.data.get('total_amount')
            receipt_amount = request.data.get('receipt_amount')
            invoice_amount = request.data.get('invoice_amount')
            payment_id = request.data.get('payment_id')
            print('SUCCESS', receipt_amount)
            self.pay_success(request, order, trade_no, receipt_amount, payment_id)
        else:
            self.pay_failed(request, order)
        return HttpResponse('success')


class WxpayOrderPayProviderCallbackView(BaseOrderPayCallbackView):
    """微信支付订单支付-回调（Provider）"""
    permission_classes = ()
    parser_classes = (XmlParser,)

    def post(self, request, *args, **kwargs):
        from common import wx
        ret = {}
        status, code, data = wx.process_pay_notify_callback(WX, request.body.decode())
        out_trade_no = data.get('out_trade_no')
        trade_no = data.get("transaction_id")
        order = Order.objects.get(no=out_trade_no)
        if not status:
            ret['return_code'] = code
            ret['return_msg'] = "签名错误"
            self.pay_failed(request, order)
        elif data['result_code'] != 'SUCCESS':
            ret['return_code'] = 'FAIL'
            ret['return_msg'] = '微信返回result_code标记未成功'
            self.pay_failed(request, order)
        else:
            ret['return_code'] = 'SUCCESS'
            ret['return_msg'] = 'OK'
            total_mount = Decimal(str(data['total_fee'])) / Decimal("100.00")
            payment_id = None
            self.pay_success(request, order, trade_no, total_mount, payment_id)
        return HttpResponse(wx.dict_to_xml(ret))


class PickupGiftpack(BaseAPIView):
    permission_classes = ()
    def post(self, request, *args, **kwargs):
        from apps.user.models import AuthCode
        import time, datetime
        from apps.product.models import MarketOrder
        mobile = request.data.get('mobile', '')
        authcode = request.data.get('authcode', '')
        authcode_id = request.data.get('authcode_id', '')
        market_order_id = request.data.get('market_order_id', '')
        market_order_id = market_order_id.lower()

        ac = AuthCode.objects.filter(pk=authcode_id, code=authcode, mobile=mobile).first()
        if not ac:
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='验证码错误')
        if ac.expire_at < time.time():
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='验证码已过期')

        market_order = MarketOrder.objects.filter(id=market_order_id, as_gift_multiple=True, status=MarketOrder.Status.ING.name).first()  # type: MarketOrder
        if not market_order:
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='礼物包不存在或已过期')

        user, created = User.objects.get_or_create(mobile=mobile)
        if created:
            user.nickname = User.get_nickname()
            user.state = User.State.INACTIVE.name
            user.source = User.Source.BE_GIFTED.name
            user.save()

        if user.id == market_order.user_id:
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='自己不能领取哦')

        picked_sos = SubOrder.objects.filter(market_order_id=market_order.id)
        picked_order_ids = [e.order_id for e in picked_sos]
        if Order.objects.filter(id__in=picked_order_ids, buyer_user_id=user.id):
            raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='已领取过')

        with transaction.atomic():
            gb = GoodsBlock.objects.select_for_update().filter(market_order=market_order).first()  # type: GoodsBlock
            if not gb:
                raise JsonAPIException(code=ErrCode.PARAMETER_ERROR.name, msg='礼物已经被领取完')

            seller = gb.owner_user_id
            gb.owner_user_id = user.id
            gb.trade_type = GoodsBlock.TradeType.MARKET.name
            gb.trade_price = gb.product.last_trade_price
            gb.market_order = None
            gb.locked_by_user_id = None
            gb.locked_expire_at = 0
            gb.save()

            # 仓储天数
            now = datetime.datetime.now()
            start = gb.trade_datetime
            cha_time = now - start
            days = cha_time.days + 1

            seller_block = GoodsBlockChain.objects.create(goods_block_id=gb.id,
                                                          operator_user_id=seller,
                                                          chain_type=GoodsBlockChain.ChainType.DIRECT_GIVE.name,
                                                          node_datetime=datetime.datetime.now(),
                                                          storage_repo_id=gb.repo_id,
                                                          storage_repo_days=days
                                                          )
            buyer_block = GoodsBlockChain.objects.create(goods_block_id=gb.id,
                                                         operator_user_id=user.id,
                                                         chain_type=GoodsBlockChain.ChainType.ACCEPT.name,
                                                         node_datetime=datetime.datetime.now(),
                                                         storage_repo_id=gb.repo_id,
                                                         storage_repo_days=days
                                                         )

            # 创建订单
            order = Order.objects.create(
                no=Order.make_order_no(mobile), amount=Decimal('0.00'), payment_method=Order.PaymentMethod.BALANCE.name,
                status=Order.Status.FINISHED.name, expire_at=time.time(), buyer_user_id=user.id,
                as_gift=True, as_gift_multiple=True, as_gift_pre_pay_repo_cost=True, as_gift_pre_pay_repo_cost_amount=Decimal('0.00'),
                repo_amount=Decimal('0.00'), repo_preferential_amount=Decimal('0.00'), repo_real_pay_amount=Decimal('0.00'),
                post_finished_done=True,
            )
            # 创建子订单
            SubOrder.objects.create(
                order=order, goods_block_id=gb.id, product_id=gb.product.id, product_name=gb.product.name, goods_block_repo_id=gb.repo_id,
                goods_block_repo_name=gb.repo.name, store_unit_id=gb.store_unit_id, price_per_100g_1d=gb.repo_cost_price_per_100g_1d,
                amount=Decimal('0.00'), seller_user_id=market_order.user_id, market_order_id=market_order.id, create_type=SubOrder.CreateType.MARKET_BUY_IN.name,
                repo_amount=gb.repo_amount, repo_cost_start_datetime=gb.trade_datetime, repo_cost_end_datetime=datetime.datetime.now(),
                goods_block_to_repo_id=gb.repo.id, goods_block_to_repo_name=gb.repo.name,
            )

            if SubOrder.objects.filter(market_order_id=market_order.pk).count() == market_order.count:
                market_order.status = MarketOrder.Status.END.name
                market_order.save()

        return Response({})